home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / QuickTime VR / MacOS / QuickDraw™ 3D 1.0.6F4 SDK / Samples / SampleCode / Tumbler and Podium / Tumbler_event.c < prev    next >
Encoding:
Text File  |  1995-11-15  |  15.7 KB  |  635 lines  |  [TEXT/MPS ]

  1. //        Tumbler)event.c
  2. //
  3. //        Event handling routines.
  4. //
  5. //        Author:        Nick Thompson & Pablo Fernicola, with thanks to the QuickDraw 3D team
  6. //        Date:        Monday, Janurary 20, 1992
  7. //
  8. //        Copyright © 1992-95 Apple Computer, Inc., All Rights Reserved
  9. //
  10. //    Modification History:
  11. //        12/2/94        nick        
  12.  
  13. //
  14. //    Debugging Aids :
  15. //
  16. //    Turn this flag on to see where the current hilite region is.
  17. //
  18. //        #define    _FLASH_HILITE_RGN_
  19. //
  20. //
  21.  
  22. #include <Drag.h>
  23. #include "QD3D.h"
  24.  
  25. #include "Tumbler_globals.h"
  26. #include "Tumbler_prototypes.h"
  27. #include "Tumbler_resources.h"
  28. #include "AppleEvents.h"
  29. #include "Events.h"
  30.  
  31. #include "QD3DView.h"
  32. #include "QD3DDrawContext.h"
  33. #include "QD3DDrawContext.h"
  34. #include "QD3DPick.h"
  35. #include "QD3DTransform.h"
  36. #include "QD3DLight.h"
  37. #include "QD3DMath.h"
  38. #include "QD3DGeometry.h"
  39.  
  40. #define    SleepDuration        20        /* WaitNextEvent sleep constant        */
  41.  
  42. #include "Tumbler_event.h"
  43. #include "Tumbler_camera.h"
  44. #include "Tumbler_drag.h"
  45. #include "Tumbler_offscreen.h"
  46. #include "Tumbler_windows.h"
  47. #include "Tumbler_menus.h"
  48. #include "Tumbler_drag.h"
  49. #include "Tumbler_document.h"
  50. #include "Tumbler_cursor.h"
  51.  
  52. #ifdef PODIUM_APP
  53.     #include "Tumbler_Podium.h"
  54. #endif
  55.  
  56. static void DoContentClick(WindowPtr theWindow, EventRecord *theEvent);
  57. static void DoBackgroundContentClick(WindowPtr theWindow, EventRecord *theEvent) ;
  58. static void DoMouseDown(EventRecord *theEvent);
  59. static void DoKey(char theChar);
  60. static void DoKeyDown(EventRecord *theEvent);
  61. static void DoActivate(EventRecord *theEvent);
  62. static void DoUpdate(EventRecord *theEvent);
  63. static void DoOSEvent(EventRecord *theEvent);
  64. static void DoHighLevelEvent(EventRecord *theEvent);
  65. static void DoEvent(EventRecord *theEvent);
  66. static void DoIdleHitTest(void);
  67. static void DoIdle(void);
  68.  
  69.  
  70.  
  71.  
  72.  
  73. //-------------------------------------------------------------------------------------
  74. //    DoContentClick handles mouseDown events in the content region of a document window.
  75. //
  76. //    (1)    If the mouseDown is on a draggable object (the document's hiliteRgn) and a
  77. //        successful drag occurs, no further processing is necessary.
  78. //
  79. //    (2)    If the mouseDown is not on a draggable object and within the viewRect of the
  80. //        TextEdit field, call TEClick to handle the mouseDown.
  81.  
  82. static void DoContentClick( WindowPtr theWindow, EventRecord *theEvent)
  83.  
  84. {    short            thePart;
  85.     Point            thePoint;
  86.     ControlHandle    theControl;
  87.     DocumentPtr        theDocument = GetDocumentFromWindow(theWindow);
  88.     GrafPtr            savedPort ;
  89.  
  90.     if( theWindow == nil )
  91.         return ;
  92.  
  93.     GetPort( &savedPort) ;
  94.     SetPort( theWindow ) ;
  95.     
  96.     thePoint = theEvent->where;
  97.     GlobalToLocal(&thePoint);
  98.  
  99.     if( theDocument->documentGroup ) {
  100.     
  101.         
  102.         // we can only do a drag if the option key is held down
  103.     
  104.         if (theEvent->modifiers & optionKey) {
  105.             RgnHandle    tempRgn = NewRgn();  // Nick this needs to be the BBox of the group
  106.             
  107.             RectRgn(tempRgn, &theWindow->portRect);
  108.             DoDragObjects(theDocument, theEvent, tempRgn ) ;
  109.             
  110.             DisposeRgn(tempRgn);
  111.         } else {
  112.             Point     oldMouse;
  113.             Point     newMouse;
  114.             long     mouseChanged = 0;
  115.             long    dx, dy, x, y, oldX, oldY;
  116.             float    width, height;
  117.             float    xRot, yRot;
  118.                     
  119.             GetMouse(&newMouse);        // get the mouse in local co-ordinates, 
  120.                                             // local to the  current GrafPort
  121.     
  122.             oldX = newMouse.h;
  123.             oldY = newMouse.v;
  124.             
  125.             width = theWindow->portRect.left - theWindow->portRect.right;
  126.             height = theWindow->portRect.bottom - theWindow->portRect.top;
  127.  
  128.             while (WaitMouseUp()) {
  129.             
  130.                 GetMouse(&newMouse);        // get the mouse in local co-ordinates, 
  131.                                             // local to the  current GrafPort
  132.  
  133.                 dx = oldY - newMouse.v;
  134.                 dy = newMouse.h - oldX;
  135.                 
  136.                 if ((dx != 0) || (dy != 0)) {
  137.                     TQ3Matrix4x4        tempMatrix;
  138.                     
  139.                     xRot = ((float) dx * kQ3Pi) / width;
  140.                     yRot = ((float) dy * kQ3Pi) / height;
  141.         
  142.                     if ((xRot != 0.0) || (yRot != 0.0)) {
  143.                         Q3Matrix4x4_SetRotate_XYZ(&tempMatrix, xRot, yRot, 0.0);
  144.                         Q3Matrix4x4_Multiply(&theDocument->modelRotation, &tempMatrix, &theDocument->modelRotation);
  145.  
  146.                         mouseChanged = 1;
  147.                         DrawOffscreen(theDocument);
  148.                     }
  149.                 }
  150.                 oldX = newMouse.h; oldY = newMouse.v;
  151.             }
  152.             
  153.             if( mouseChanged ) {
  154.                 theDocument->rotationDir.x = xRot;
  155.                 theDocument->rotationDir.y = yRot;
  156.                 DrawOffscreen(theDocument);
  157.                 
  158.                 DoDrawGrowIcon(theDocument->theWindow);
  159.             }
  160.         }
  161.     }
  162.  
  163.     SetPort( savedPort ) ;
  164.  
  165. }
  166.  
  167.  
  168. //
  169. //    DoBackgroundContentClick handles mouseDown events in the content region of a document window
  170. //    when the window is not frontmost. The following bullet items describe how this background
  171. //    mouseDown event is handled:
  172. //
  173. //    (1)    If the mouseDown is not in a draggable object (not in the document's hiliteRgn) call
  174. //        SelectWindow to bring the window to the front as usual.
  175. //
  176. //    (2)    If the mouseDown is in a draggable object and the mouse is released without
  177. //        dragging, call SelectWindow when the mouse is released.
  178. //
  179. //    (3)    If the mouseDown is in a draggable object and a successful drag occurs, SelectWindow
  180. //        should only be called if the drop occurred in the same window (the DoDragObjects function
  181. //        calls SelectWindow in this case).
  182. //
  183.  
  184. static void DoBackgroundContentClick(WindowPtr theWindow, EventRecord *theEvent)
  185. {
  186.     short            thePart;
  187.     Point            thePoint;
  188.     ControlHandle    theControl;
  189.     DocumentPtr        theDocument ;
  190.     RgnHandle        tempRgn = NewRgn(); // Nick will fix later, needs to be the bbox of the group
  191.     
  192.     if( theWindow == nil )
  193.         return ;
  194.  
  195.     SetPort( theWindow );
  196.     theDocument = GetDocumentFromWindow(theWindow);
  197.  
  198.     thePoint = theEvent->where;
  199.     GlobalToLocal(&thePoint);
  200.  
  201.     RectRgn(tempRgn, &theWindow->portRect);
  202.     
  203.     if (PtInRgn(thePoint, tempRgn)) {
  204.  
  205.         if (! DoDragObjects(theDocument, theEvent, tempRgn)) {
  206.             SelectWindow(theDocument->theWindow);
  207.         }
  208.  
  209.     } else {
  210.  
  211.         SelectWindow(theDocument->theWindow);
  212.  
  213.     }
  214.     DisposeRgn( tempRgn );
  215. }
  216.  
  217.  
  218. //
  219. //    DoMouseDown is called to handle mouseDown events.
  220. //
  221.  
  222. static void DoMouseDown(EventRecord *theEvent)
  223.  
  224. {    short        thePart;
  225.     WindowPtr    theWindow;
  226.     Rect        dragRect;
  227.     DocumentPtr theDocument;
  228.     
  229.  
  230.     thePart = FindWindow(theEvent->where, &theWindow);
  231.     switch(thePart) {
  232.     
  233.         case inMenuBar:
  234.             PrepareMenus();
  235.             DoMenuCommand(MenuSelect(theEvent->where));
  236.             break;
  237.             
  238.         case inSysWindow:
  239.             SystemClick(theEvent, theWindow);
  240.             break;
  241.         case inContent:
  242.         
  243.             if (theWindow == FrontWindow()) {
  244. #ifndef PODIUM_APP
  245.                 DoContentClick(theWindow, theEvent);
  246. #else
  247.                 Podium_DoContent( GetDocumentFromWindow(theWindow), theEvent ) ;
  248. #endif
  249.             } else {
  250. #ifndef PODIUM_APP
  251.                 DoBackgroundContentClick(theWindow, theEvent);
  252. #else
  253.                 Podium_DoBackgroundContent( GetDocumentFromWindow(theWindow), theEvent ) ;
  254. #endif
  255.             }
  256.             break;
  257.             
  258.         case inDrag:
  259.             if (theWindow != FrontWindow())
  260.                 SelectWindow(theWindow);
  261.             dragRect = qd.screenBits.bounds;
  262.             DragWindow(theWindow, theEvent->where, &dragRect);
  263.             break;
  264.             
  265.         case inGrow:
  266.             
  267.             if ((theDocument = GetDocumentFromWindow(theWindow)) != nil) {
  268.                 GrowDocumentWindow(theWindow, theEvent->where);
  269.             }
  270.             break;
  271.             
  272.         case inGoAway:
  273.             if ((theDocument = GetDocumentFromWindow(theWindow)) != nil)
  274.                 if (TrackGoAway(theWindow, theEvent->where)) {
  275.                     (void)CloseDocument(theDocument);        // it's not important what the result is here
  276.                 }
  277.             break;
  278.     }
  279. }
  280.  
  281.  
  282. //
  283. //    DoKey is called each time a character is typed on the keyboard to
  284. //    be entered into a document window.
  285. //
  286.  
  287. static void DoKey(char theChar)
  288.  
  289. {    WindowPtr        theWindow;
  290.     DocumentPtr theDocument;
  291.  
  292.     if ((theWindow = FrontWindow()) != nil) {
  293.         if ((theDocument = GetDocumentFromWindow(theWindow)) != nil) {
  294.             // what d'ya want to do here?
  295.         }
  296.     }
  297. }
  298.  
  299.  
  300. //
  301. //    DoKeyDown is called to handle keyDown or autoKey events.
  302. //
  303.  
  304. static void DoKeyDown(EventRecord *theEvent)
  305.  
  306. {    char        theChar;
  307.  
  308.     theChar = theEvent->message & charCodeMask;
  309.  
  310.     if (theEvent->modifiers & cmdKey) {
  311.         PrepareMenus();
  312.         DoMenuCommand(MenuKey(theChar));
  313.     }
  314. }
  315.  
  316.  
  317. //
  318. //    DoActivate is called in response to activate/deactivate events.
  319. //
  320.  
  321. static void DoActivate(EventRecord *theEvent)
  322.  
  323. {    WindowPtr        theWindow;
  324.     DocumentPtr theDocument;
  325.  
  326.     if ((theWindow = (WindowPtr) theEvent->message) != nil) {
  327.         if ((theDocument = GetDocumentFromWindow(theWindow)) != nil) {
  328.             DoActivateDocument(theDocument, (theEvent->modifiers & activeFlag));
  329.         }
  330.     }
  331. }
  332.  
  333.  
  334. //
  335. //    DoUpdate is called in response to update events.
  336. //
  337.  
  338. static void DoUpdate(EventRecord *theEvent)
  339.  
  340. {    DocumentPtr theDocument;
  341.  
  342.     if ( ((WindowPtr) theEvent->message) != nil)
  343.         UpdateWindow((WindowPtr) theEvent->message);
  344. }
  345.  
  346.  
  347. //
  348. //    DoOSEvent is called in response to Operating System events.
  349. //
  350.  
  351. static void DoOSEvent(EventRecord *theEvent)
  352.  
  353. {    DocumentPtr theDocument;
  354.  
  355.     switch ((theEvent->message >> 24) & 0x0FF) {
  356.         case suspendResumeMessage:
  357.             gInBackground = (theEvent->message & resumeFlag) == 0;
  358.             if ((theDocument = GetDocumentFromWindow(FrontWindow())) != nil)
  359.                 DoActivateDocument(theDocument, !gInBackground);
  360.             break;
  361.     }
  362. }
  363.  
  364.  
  365.  
  366.  
  367. static void DoHighLevelEvent(EventRecord *theEvent)
  368. {
  369.     AEProcessAppleEvent(theEvent);
  370. }
  371.  
  372.  
  373. //
  374. //    Each time WaitNextEvent returns an event to this application, DoEvent
  375. //    is called to handle the event.
  376. //
  377.  
  378. static void DoEvent(EventRecord *theEvent)
  379.  
  380. {    WindowPtr        theWindow;
  381.     DocumentPtr theDocument;
  382.  
  383.     if ((theWindow = FrontWindow()) != nil) {
  384.         if ((theDocument = GetDocumentFromWindow(theWindow)) != nil) {
  385.             gFrontDocument = theDocument;
  386.         }
  387.     }
  388.  
  389.     switch(theEvent->what) {
  390.         case mouseDown:
  391.             DoMouseDown(theEvent);
  392.             break;
  393.         case mouseUp:
  394.             break;
  395.         case keyDown:
  396.         case autoKey:
  397.             DoKeyDown(theEvent);
  398.             break;
  399.         case activateEvt:
  400.             DoActivate(theEvent);
  401.             break;
  402.         case updateEvt:
  403.             DoUpdate(theEvent);
  404.             break;
  405.         case osEvt:
  406.             DoOSEvent(theEvent);
  407.             break;
  408.         case kHighLevelEvent:
  409.             DoHighLevelEvent(theEvent);
  410.             break;
  411.     }
  412. }
  413.  
  414.  
  415. //
  416. //    DoIdle get called repetitively while the application is not doing
  417. //    anything.
  418. //
  419.  
  420. static void DoIdleHitTest(void)
  421.  
  422. {
  423.  
  424.     WindowPtr        theWindow;
  425.     DocumentPtr theDocument;
  426.  
  427.     if ((theWindow = FrontWindow()) != nil) {
  428.         if ((theDocument = GetDocumentFromWindow(theWindow)) != nil) {
  429.             SetPort(theDocument->theWindow);
  430.  
  431.             if( theDocument->documentGroup ) {
  432.                 Point        screenPoint;
  433.                 TQ3WindowPointPickData    withData;
  434.                 unsigned long        numPicked;
  435.                 TQ3PickObject        pickObject;
  436.                 
  437.                 withData.data.sort             =    kQ3PickSortNone;
  438.                 withData.data.numHitsToReturn=    1;
  439.                 withData.data.mask             =    kQ3PickDetailMaskObject;
  440.                                               
  441.                 GetMouse( &screenPoint );
  442.                 withData.point.x = screenPoint.h;
  443.                 withData.point.y = screenPoint.v;
  444.             
  445.                 withData.vertexTolerance = withData.edgeTolerance = 3;
  446. // gone and sadly missed in b1c1, delete this line at b2c1!!
  447. //                withData.view = theDocument->theView;
  448.             
  449.                 pickObject = Q3WindowPointPick_New(&withData);
  450.         
  451.                 Q3View_StartPicking(theDocument->theView, pickObject);
  452.                 do {
  453.                     Q3DisplayGroup_Submit(theDocument->documentGroup, theDocument->theView);
  454.                 } while (Q3View_EndPicking(theDocument->theView) == kQ3ViewStatusRetraverse);
  455.                 
  456.                 if (Q3Pick_GetNumHits(pickObject, &numPicked) && (numPicked != 0)) {
  457.                     SetCursor(*GetCursor(plusCursor));
  458.                 } else {
  459.                     SetCursor(&qd.arrow);
  460.                 }
  461.                 
  462.                 Q3Object_Dispose(pickObject);
  463.             }
  464.  
  465. #ifdef _FLASH_HILITE_RGN_
  466.  
  467.             {    long            dTime;
  468.  
  469.                 InvertRgn(theDocument->hiliteRgn);
  470.                 Delay(10, &dTime);
  471.                 InvertRgn(theDocument->hiliteRgn);
  472.             }
  473. #endif
  474.  
  475.         }
  476.     }
  477. }
  478.  
  479. //
  480. //    DoIdle get called repetitively while the application is not doing
  481. //    anything.
  482. //
  483.  
  484. static void DoIdle(void)
  485.  
  486. {
  487.  
  488.     WindowPtr        theWindow;
  489.     DocumentPtr theDocument;
  490.  
  491.     if ((theWindow = FrontWindow()) != nil) {
  492.         if ((theDocument = GetDocumentFromWindow(theWindow)) != nil) {
  493.             Boolean    update = false;
  494.             
  495.             SetPort(theDocument->theWindow);
  496.  
  497.             if( theDocument->documentGroup && theDocument->animateLights && theDocument->light) {
  498. #if defined(ESCHER_VER_15) && ESCHER_VER_15
  499.  
  500.                 float angle;
  501.                 TQ3GroupPosition        lightPosition, position;
  502.                 TQ3LightObject        theLight;
  503.                 TQ3GroupObject        lightGroup;
  504.                 TQ3Matrix4x4            matrix;
  505.                 TQ3Point3D            location;
  506.                 TQ3Object            ellipsoid;
  507.                 TQ3Point3D            origin;
  508.                 
  509.                 theDocument->light = kQ3True;
  510.                 
  511.                 Q3View_GetLightGroup(theDocument->theView, &lightGroup);
  512.                 Q3Group_GetFirstPosition(lightGroup, &lightPosition);
  513.                         
  514.                 /* First one is always on, skip */
  515.                 Q3Group_GetNextPosition(lightGroup, &lightPosition);
  516.  
  517.                 /* Adjust the transform for the Red sphere */
  518.                 Q3RotateTransform_GetAngle(theDocument->lightXform1, &angle);
  519.                 angle += 0.8;
  520.                 Q3RotateTransform_SetAngle(theDocument->lightXform1, angle);
  521.                 Q3Transform_GetMatrix(theDocument->lightXform1, &matrix);
  522.                 
  523.                 /* Get the Red light */
  524.                 Q3Group_GetPositionObject(lightGroup, lightPosition, &theLight);
  525.                 /* Get the Red sphere */
  526.                 Q3Group_GetFirstPositionOfType(theDocument->light1,
  527.                     kQ3ShapeTypeGeometry, &position);
  528.             
  529.                 Q3Group_GetPositionObject(theDocument->light1, position, &ellipsoid);
  530.                 Q3Ellipsoid_GetOrigin( ellipsoid, &origin);
  531.  
  532.                 Q3Point3D_Transform(&origin, &matrix, &location);
  533.                 Q3PointLight_SetLocation(theLight, &location);
  534.                 Q3Object_Dispose(theLight);                        
  535.                 Q3Object_Dispose(ellipsoid);                        
  536.                 
  537.                 /* Adjust the transform for the Green sphere */
  538.                 Q3Group_GetNextPosition(lightGroup, &lightPosition);
  539.                 Q3RotateTransform_GetAngle(theDocument->lightXform2, &angle);
  540.                 angle += 0.5;
  541.                 Q3RotateTransform_SetAngle(theDocument->lightXform2, angle);
  542.                 Q3Transform_GetMatrix(theDocument->lightXform2, &matrix);
  543.                         
  544.                 /* Get the Green light */
  545.                 Q3Group_GetPositionObject(lightGroup, lightPosition, &theLight);
  546.                 /* Get the Green sphere */
  547.                 Q3Group_GetFirstPositionOfType(theDocument->light2,
  548.                     kQ3ShapeTypeGeometry, &position);
  549.             
  550.                 Q3Group_GetPositionObject(theDocument->light2, position, &ellipsoid);
  551.                 Q3Ellipsoid_GetOrigin( ellipsoid, &origin);
  552.                 Q3Point3D_Transform(&origin, &matrix, &location);
  553.                 Q3PointLight_SetLocation(theLight, &location);
  554.                 Q3Object_Dispose(theLight);                        
  555.                 Q3Object_Dispose(ellipsoid);                        
  556.                         
  557.                 /* Adjust the transform for the Blue sphere */
  558.                 Q3Group_GetNextPosition(lightGroup, &lightPosition);
  559.                 Q3RotateTransform_GetAngle(theDocument->lightXform3, &angle);
  560.                 angle += 0.3;
  561.                 Q3RotateTransform_SetAngle(theDocument->lightXform3, angle);
  562.                 Q3Transform_GetMatrix(theDocument->lightXform3, &matrix);
  563.                         
  564.                 /* Get the Blue light */
  565.                 Q3Group_GetPositionObject(lightGroup, lightPosition, &theLight);
  566.                 /* Get the Blue sphere */
  567.                 Q3Group_GetFirstPositionOfType(theDocument->light3,
  568.                     kQ3ShapeTypeGeometry, &position);
  569.             
  570.                 Q3Group_GetPositionObject(theDocument->light3, position, &ellipsoid);
  571.                 Q3Ellipsoid_GetOrigin( ellipsoid, &origin);
  572.                 Q3Point3D_Transform(&origin, &matrix, &location);
  573.                 Q3PointLight_SetLocation(theLight, &location);
  574.                 Q3Object_Dispose(theLight);                        
  575.                 Q3Object_Dispose(ellipsoid);                        
  576.  
  577.                 Q3Object_Dispose(lightGroup);
  578.                 update = true;
  579. #endif
  580.             }
  581.  
  582.             if( theDocument->documentGroup && theDocument->animateModel) {
  583.                 TQ3Matrix4x4    tmp;
  584.                 
  585.                 if( theDocument->rotationDir.x == 0.0 && theDocument->rotationDir.y == 0.0 ) {
  586.                     Q3Matrix4x4_SetRotate_XYZ(&tmp, 0.03, 0.08, 0.0);
  587.                     Q3Matrix4x4_Multiply(&theDocument->modelRotation, &tmp, &theDocument->modelRotation);
  588.                 } else {
  589.                     Q3Matrix4x4_SetRotate_XYZ(&tmp, theDocument->rotationDir.x, theDocument->rotationDir.y, 0.0);
  590.                     Q3Matrix4x4_Multiply(&theDocument->modelRotation, &tmp, &theDocument->modelRotation);
  591.                 }
  592.                 update = true;
  593.             }
  594.  
  595.             if( update ) {
  596.                 DrawOffscreen(theDocument);
  597.                 DrawOnscreen(theDocument);
  598.                 DoDrawGrowIcon(theDocument->theWindow);
  599.             }
  600.         }
  601.     }
  602. }
  603.  
  604.  
  605. //
  606. //    This is the main event loop of the program. It calls WaitNextEvent
  607. //    and dispatches the returned event until gQuit is true.
  608. //
  609.  
  610. void EventLoop(void)
  611.  
  612. {    short            gotEvent;
  613.     EventRecord        theEvent;
  614.     RgnHandle        theMouseRgn;
  615.     Point            theLoc;
  616.  
  617.     theMouseRgn = NewRgn();
  618.  
  619.     do {
  620.     
  621.         gotEvent = WaitNextEvent(everyEvent, &theEvent, 0L, theMouseRgn);
  622.         if (gotEvent) {
  623.             DoEvent(&theEvent);
  624.         } else {
  625. #ifndef PODIUM_APP
  626.             DoIdle();
  627. #else
  628.             Podium_DoIdle(&theEvent) ;
  629. #endif
  630.         }
  631.     } while (! gQuit);
  632.  
  633.     DisposeRgn(theMouseRgn);
  634. }
  635.